home *** CD-ROM | disk | FTP | other *** search
/ Revista CD Expert 8 / Revista CD Expert nº 08 CD1.iso / Utilitarios / Programacao / Pacific C for DOS / EXAMPLES / MOUSE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-15  |  13.8 KB  |  645 lines

  1. #include    <dos.h>
  2. #include    <stdlib.h>
  3. #include    "mouse.h"
  4.  
  5. /*
  6.  *    Mouse driver interface code for standard INT 33h mouse driver.
  7.  *    This C version replaces the earlier memory model specific assembler
  8.  *    versions.  The 80386 assembler version (mouse_f.as) should still be
  9.  *    used for flat model, due to the need to handle interaction between
  10.  *    real and protected mode using DOS extender system calls.
  11.  *
  12.  *    Colin Weaver, HI-TECH Software        June 1992
  13.  *
  14.  *    This code assumes that the int86x() function returns the new values
  15.  *    of the segment registers in the "SREGS" strcture passed.
  16.  */
  17.  
  18. #define    DOS_INT        0x21        /* MS-DOS: int 21h */
  19. #define    MOUSE_INT    0x33        /* Mouse driver: int 33h */
  20.  
  21. #define    ushort        unsigned short
  22. #define    ulong        unsigned long
  23. #define    FPTR_SEG(ptr)    (((long)(far void (*)(void))(ptr)) >> 16)
  24. #define    GLUE_STACK_SIZE    256
  25.  
  26. far volatile unsigned long *    _TICK_COUNT_ = (far unsigned long *) 0x0040006CL;
  27. static far unsigned short    KBSTATUS  @ 0x00400017L;
  28.  
  29. /*
  30.  *    int    initmouse(void)
  31.  *
  32.  *    Initialize the mouse driver, return the number of buttons, or -1 on
  33.  *    failure.
  34.  */
  35.  
  36. int
  37. initmouse(void)
  38. {
  39.     union REGS    reg;
  40.     struct SREGS    seg;
  41.  
  42.     reg.x.ax = 0x3533;        /* funcion 35H, get vector: 33H */
  43.     int86x(DOS_INT, ®, ®, &seg);
  44.     if (reg.x.bx == 0 && seg.es == 0)
  45.         return -1;        /* no mouse driver */
  46.     reg.x.ax = 0;            /* function 0: reset mouse */
  47.     int86(MOUSE_INT, ®, ®);
  48.     if (reg.x.ax == 0)
  49.         return -1;        /* mouse not present */
  50.     return reg.x.bx;        /* return button count */
  51. }
  52.  
  53. /*
  54.  *    void    shutdownmouse(void)
  55.  *
  56.  *    Shut down mouse driver - dummy on PC
  57.  */
  58.  
  59. void
  60. shutdownmouse(void)
  61. {
  62.     eventhandler(0, NULL);
  63. }
  64.  
  65. /*
  66.  *    void    showcursor(void)
  67.  *
  68.  *    Increment the cursor hide/show level
  69.  */
  70.  
  71. void
  72. showcursor(void)
  73. {
  74.     union REGS    reg;
  75.  
  76.     reg.x.ax = 1;            /* function 1: show cursor */
  77.     int86(MOUSE_INT, ®, ®);
  78. }
  79.  
  80. /*
  81.  *    void    hidecursor(void)
  82.  *
  83.  *    Decrement the cursor hide/show level
  84.  */
  85.  
  86. void
  87. hidecursor(void)
  88. {
  89.     union REGS    reg;
  90.  
  91.     reg.x.ax = 2;            /* function 2: hide cursor */
  92.     int86(MOUSE_INT, ®, ®);
  93. }
  94.  
  95. /*
  96.  *    void    readmouse(struct mousedata * mouse)
  97.  *
  98.  *    Read mouse position and button status
  99.  */
  100.  
  101. void
  102. readmouse(struct mousedata * mouse)
  103. {
  104.     union REGS    reg;
  105.  
  106.     reg.x.ax = 3;            /* function 3: read pos'n & status */
  107.     int86(MOUSE_INT, ®, ®);
  108.     mouse->timer = *_TICK_COUNT_;
  109.     mouse->buttons = reg.x.bx;
  110.     mouse->x = reg.x.cx;
  111.     mouse->y = reg.x.dx;
  112. }
  113.  
  114. /*
  115.  *    void    setmousepos(int row, int col)
  116.  *
  117.  *    Set mouse position to (row, col)
  118.  */
  119.  
  120. void
  121. setmousepos(int row, int col)
  122. {
  123.     union REGS    reg;
  124.  
  125.     reg.x.cx = col;
  126.     reg.x.dx = row;
  127.     reg.x.ax = 4;            /* function 4: set cursor position */
  128.     int86(MOUSE_INT, ®, ®);
  129. }
  130.  
  131. /*
  132.  *    void    getpressinfo(int button, struct mousedata * mouse)
  133.  *
  134.  *    Return number of button presses for specified button
  135.  */
  136.  
  137. void
  138. getpressinfo(int button, struct mousedata * mouse)
  139. {
  140.     union REGS    reg;
  141.  
  142.     reg.x.ax = 5;            /* function 5: get button press info */
  143.     reg.x.bx = button;
  144.     int86(MOUSE_INT, ®, ®);
  145.     mouse->timer = *_TICK_COUNT_;
  146.     mouse->buttons = reg.x.ax;
  147.     mouse->count = reg.x.bx;
  148.     mouse->x = reg.x.cx;
  149.     mouse->y = reg.x.dx;
  150. }
  151.  
  152. /*
  153.  *    void    getreleaseinfo(int button, struct mousedata * mouse)
  154.  *
  155.  *    Return number of button releases for specified button
  156.  */
  157.  
  158. void
  159. getreleaseinfo(int button, struct mousedata * mouse)
  160. {
  161.     union REGS    reg;
  162.  
  163.     reg.x.ax = 6;            /* function 6: get release info */
  164.     reg.x.bx = button;
  165.     int86(MOUSE_INT, ®, ®);
  166.     mouse->timer = *_TICK_COUNT_;
  167.     mouse->buttons = reg.x.ax;
  168.     mouse->count = reg.x.bx;
  169.     mouse->x = reg.x.cx;
  170.     mouse->y = reg.x.dx;
  171. }
  172.  
  173. /*
  174.  *    void    sethlimits(int min, int max)
  175.  *
  176.  *    Set horizontal mouse movement bounds
  177.  */
  178.  
  179. void
  180. sethlimits(int min, int max)
  181. {
  182.     union REGS    reg;
  183.  
  184.     reg.x.ax = 7;            /* function 7: set horizontal limits */
  185.     reg.x.cx = min;
  186.     reg.x.dx = max;
  187.     int86(MOUSE_INT, ®, ®);
  188. }
  189.  
  190. /*
  191.  *    void    setvlimits(int min, int max)
  192.  *
  193.  *    Set vertical mouse movement bounds
  194.  */
  195.  
  196. void
  197. setvlimits(int min, int max)
  198. {
  199.     union REGS    reg;
  200.  
  201.     reg.x.ax = 8;            /* function 8: set vertical limits */
  202.     reg.x.cx = min;
  203.     reg.x.dx = max;
  204.     int86(MOUSE_INT, ®, ®);
  205. }
  206.  
  207. /*
  208.  *    void    setgrcursor(struct graphic_cursor * cursor)
  209.  *
  210.  *    Set the graphics mode cursor
  211.  */
  212.  
  213. void
  214. setgrcursor(struct graphic_cursor * cursor)
  215. {
  216.     union REGS    reg;
  217.     struct SREGS    seg;
  218.  
  219.     reg.x.ax = 9;            /* function 9: set graphic cursor */
  220.     reg.x.bx = cursor->hotspot_x;
  221.     reg.x.cx = cursor->hotspot_y;
  222.     reg.x.dx = FP_OFF(cursor);
  223.     seg.es = FP_SEG(cursor);
  224.     int86x(MOUSE_INT, ®, ®, &seg);
  225. }
  226.  
  227. /*
  228.  *    void    setcursor(int type,
  229.  *            unsigned int smask_char, unsigned int smask_attr,
  230.  *            unsigned int cmask_char, unsigned int cmask_attr);
  231.  *
  232.  *    Set the text mode cursor type and masks
  233.  */
  234.  
  235. void
  236. setcursor(int type, unsigned int smask_char, unsigned int smask_attr,
  237.             unsigned int cmask_char, unsigned int cmask_attr)
  238. {
  239.     union REGS    reg;
  240.  
  241.     reg.x.ax = 10;            /* function 10: set text cursor */
  242.     reg.x.bx = type;
  243.     reg.x.cx = (smask_char & 0xFF) | (smask_attr << 8);
  244.     reg.x.dx = (cmask_char & 0xFF) | (cmask_attr << 8);
  245.     int86(MOUSE_INT, ®, ®);
  246. }
  247.  
  248. /*
  249.  *    void    readcounters(struct mousedata * mouse)
  250.  *
  251.  *    Read the mouse motion counters (deltas from last read)
  252.  */
  253.  
  254. void
  255. readcounters(struct mousedata * mouse)
  256. {
  257.     union REGS    reg;
  258.  
  259.     reg.x.ax = 11;            /* function 11: read counters */
  260.     int86(MOUSE_INT, ®, ®);
  261.     mouse->x = reg.x.cx;
  262.     mouse->y = reg.x.dx;
  263. }
  264.  
  265. /*
  266.  *    void    setpixelratio(int vertical, int horizontal)
  267.  *
  268.  *    Set mouse motion/pixel ratio
  269.  */
  270.  
  271. void
  272. setpixelratio(int vertical, int horizontal)
  273. {
  274.     union REGS    reg;
  275.  
  276.     reg.x.ax = 15;            /* function 15: set pixel ratio */
  277.     reg.x.cx = horizontal;
  278.     reg.x.dx = vertical;
  279.     int86(MOUSE_INT, ®, ®);
  280. }
  281.  
  282. /*
  283.  *    void    conditionalhide(struct boundsrect * rect)
  284.  *
  285.  *    Conditionally hide the cursor if it is within the specified rectangle
  286.  */
  287.  
  288. void
  289. conditionalhide(struct boundsrect * rect)
  290. {
  291.     union REGS    reg;
  292.  
  293.     reg.x.ax = 16;            /* function 16: conditional hide */
  294.     reg.x.cx = rect->left;
  295.     reg.x.dx = rect->top;
  296.     reg.x.si = rect->right;
  297.     reg.x.di = rect->bottom;
  298.     int86(MOUSE_INT, ®, ®);
  299. }
  300.  
  301. /*
  302.  *    void    speedthreshold(int threshold)
  303.  *
  304.  *    Set the ballistic speed threshold, beyond which exponential mouse
  305.  *    response occurs (with supported drivers).
  306.  */
  307.  
  308. void
  309. speedthreshold(int threshold)
  310. {
  311.     union REGS    reg;
  312.  
  313.     reg.x.ax = 19;            /* function 19: set speed threshold */
  314.     reg.x.dx = threshold;
  315.     int86(MOUSE_INT, ®, ®);
  316. }
  317.  
  318. /*
  319.  *    void    setsensitivity(struct sensitivity * se)
  320.  *
  321.  *    Set the mouse sensitivity values (horizontal, vertical and
  322.  *    ballistic threshold)
  323.  */
  324.  
  325. void
  326. setsensitivity(struct sensitivity * se)
  327. {
  328.     union REGS    reg;
  329.  
  330.     reg.x.ax = 26;            /* function 26: set sensitivity */
  331.     reg.x.bx = se->horizontal;
  332.     reg.x.cx = se->vertical;
  333.     reg.x.dx = se->threshold;
  334.     int86(MOUSE_INT, ®, ®);
  335. }
  336.  
  337. /*
  338.  *    void    getsensitivity(struct sensitivity * se)
  339.  *
  340.  *    Get the mouse sensitivity values (horizontal, vertical and
  341.  *    ballistic threshold)
  342.  */
  343.  
  344. void
  345. getsensitivity(struct sensitivity * se)
  346. {
  347.     union REGS    reg;
  348.  
  349.     reg.x.ax = 27;            /* function 27: get sensitivity */
  350.     int86(MOUSE_INT, ®, ®);
  351.     se->horizontal = reg.x.bx;
  352.     se->vertical = reg.x.cx;
  353.     se->threshold = reg.x.dx;
  354. }
  355.  
  356. /*
  357.  *    size_t    getstoragesize(void)
  358.  *
  359.  *    Return the size of the buffer required to save the
  360.  *    complete driver state.
  361.  */
  362.  
  363. size_t
  364. getstoragesize(void)
  365. {
  366.     union REGS    reg;
  367.  
  368.     reg.x.ax = 21;            /* function 21: driver state size */
  369.     int86(MOUSE_INT, ®, ®);
  370.     return reg.x.bx;
  371. }
  372.  
  373. /*
  374.  *    void    savestate(void * buffer)
  375.  *
  376.  *    Save the state of the mouse driver in the specified buffer
  377.  */
  378.  
  379. void
  380. savestate(void * buffer)
  381. {
  382.     union REGS    reg;
  383.     struct SREGS    seg;
  384.  
  385.     reg.x.ax = 22;            /* function 22: save driver state */
  386.     reg.x.dx = FP_OFF(buffer);
  387.     seg.es = FP_SEG(buffer);
  388.     int86x(MOUSE_INT, ®, ®, &seg);
  389. }
  390.  
  391. /*
  392.  *    void    restorestate(void * buffer)
  393.  *
  394.  *    Restore the mouse driver state from the specified buffer
  395.  */
  396.  
  397. void
  398. restorestate(void * buffer)
  399. {
  400.     union REGS    reg;
  401.     struct SREGS    seg;
  402.  
  403.     reg.x.ax = 23;            /* function 23: restore driver state */
  404.     reg.x.dx = FP_OFF(buffer);
  405.     seg.es = FP_SEG(buffer);
  406.     int86x(MOUSE_INT, ®, ®, &seg);
  407. }
  408.  
  409. /*
  410.  *    int    savemouse(void)
  411.  *
  412.  *    Save the current mouse driver state.  This function allocates the
  413.  *    buffer required to save the driver state.
  414.  *
  415.  *    On exit:    return value == 1 if save was successful, 0 otherwise.
  416.  *
  417.  *    Two static variables are defined:
  418.  *
  419.  *    size_t    _m_savesize_    Size of buffer state (in case it changes)
  420.  *    void *    _m_saveptr_    Driver state buffer pointer
  421.  *                obtained using malloc()
  422.  */
  423.  
  424. static size_t    _m_savesize_;
  425. static void *    _m_saveptr_;
  426.  
  427. int
  428. savemouse(void)
  429. {
  430.     if (_m_saveptr_) {            /* block already allocated */
  431.         if (_m_savesize_ < getstoragesize()) {    /* large enough ? */
  432.             free(_m_saveptr_);
  433.             _m_saveptr_ = NULL;
  434.         }
  435.     }
  436.     if (!_m_saveptr_) {            /* need a new block ? */
  437.         _m_savesize_ = getstoragesize();
  438.         _m_saveptr_ = _non_ems_alloc(_m_savesize_);
  439.         if (!_m_saveptr_) {        /* did malloc() work ? */
  440.             return 0;
  441.         }
  442.     }
  443.     savestate(_m_saveptr_);
  444.     return 1;
  445. }
  446.  
  447. /*
  448.  *    int    restoremouse(void)
  449.  *
  450.  *    Restore the mouse driver state.  This function uses the buffer
  451.  *    allocated by savemouse()
  452.  *
  453.  *    Return code: 1 on success, 0 on failure.
  454.  */
  455.  
  456. int
  457. restoremouse(void)
  458. {
  459.     if (_m_saveptr_) {
  460.         restorestate(_m_saveptr_);
  461.         return 1;
  462.     } else {
  463.         return 0;
  464.     }
  465. }
  466.  
  467. /*
  468.  *    void    getmouseinfo(struct mouseinfo * minfo)
  469.  *
  470.  *    Return the mouse driver version, mouse interface type and
  471.  *    mouse IRQ number in the "minfo" structure supplied.
  472.  *
  473.  *    This function may not be available with some mouse drivers.
  474.  */
  475.  
  476. void
  477. getmouseinfo(struct mouseinfo * minfo)
  478. {
  479.     union REGS    reg;
  480.  
  481.     reg.x.ax = 36;
  482.     int86(MOUSE_INT, ®, ®);
  483.     minfo->majorver = reg.h.bh;
  484.     minfo->minorver = reg.h.bl;
  485.     minfo->mousetype = reg.h.ch;
  486.     minfo->irqnumber = reg.h.cl;
  487. }
  488.  
  489. /*
  490.  *    unsigned int    keymodbits(void)
  491.  *
  492.  *    Return the current keyboard modifier bits
  493.  */
  494.  
  495. unsigned int
  496. keymodbits(void)
  497. {
  498.     return KBSTATUS;
  499. }
  500.  
  501. /*
  502.  *    void    eventhandler(int eventbits, void (*handler)(struct mousedata *))
  503.  *
  504.  *    Install a user specified mouse event handler function.
  505.  *
  506.  *    eventbits:    mask specifying which event types are to be passed
  507.  *            to the user handler.
  508.  *
  509.  *    handler:    pointer to a user function which is called when
  510.  *            an event of one of the types specified in eventbits
  511.  *            occurs.
  512.  *
  513.  *    The user event handler is NOT called directly by the mouse driver.
  514.  *    A special "glue" routine _asm_event_glue() is installed, and is
  515.  *    responsible for setting up a sensible execution environment before
  516.  *    passing the AX, BX, CX and DX register passed by the mouse driver
  517.  *    into _c_event_glue_();
  518.  */
  519.  
  520. extern void    _asm_event_glue(void);
  521. static void    (*user_handler)(struct mousedata *);
  522.  
  523. void
  524. eventhandler(int eventbits, void (*handler)(struct mousedata *))
  525. {
  526.     union REGS    reg;
  527.     struct SREGS    seg;
  528.  
  529.     user_handler = handler;
  530.     reg.x.ax = 12;            /* function 12: install event handler */
  531.     reg.x.cx = (eventbits != -1)? eventbits : 0;
  532.     reg.x.dx = FP_OFF(_asm_event_glue);
  533.     seg.es = FPTR_SEG(_asm_event_glue);    /* function pointer segment */
  534.     int86x(MOUSE_INT, ®, ®, &seg);
  535. }
  536.  
  537. /*
  538.  *    void    _c_event_glue_(ushort DX, ushort AX, ushort BX, ushort CX)
  539.  *
  540.  *    Event handler code: called from the _asm_event_glue() assembler routine.
  541.  *    As much event processing as possible is performed using C code, the
  542.  *    _asm_event_glue() routine is used to set up a sensible environment
  543.  *    before re-entering the C code.
  544.  *
  545.  *    When called from assembler code, _c_event_glue_() takes its arguments
  546.  *    as follows:
  547.  *
  548.  *    CX    on stack
  549.  *    BX    on stack, pushed after CX
  550.  *    AX    in ax register
  551.  *    DX    in dx register
  552.  *
  553.  *    *** WARNING *** these argument conventions are HI-TECH C specific
  554.  */
  555.  
  556. void
  557. _c_event_glue_(ushort DX, ushort AX, ushort BX, ushort CX)
  558. {
  559.     static struct mousedata    mouse;
  560.  
  561.     if (user_handler) {
  562.         mouse.event = AX;
  563.         mouse.buttons = BX;
  564.         mouse.x = CX;
  565.         mouse.y = DX;
  566.         mouse.count = 0;
  567.         mouse.keymods = KBSTATUS;
  568.         mouse.timer = *_TICK_COUNT_;
  569.         (*user_handler)(&mouse);
  570.     }
  571. }
  572.  
  573. /*
  574.  *    void    _asm_event_glue(void);
  575.  *
  576.  *    Event handler code, called interrupt style from the mouse driver.
  577.  *    This routine is responsible for passing the information in the CPU
  578.  *    registers into _c_event_glue_() routine, which in turn calls the user
  579.  *    supplied handler with the structure as an argument.
  580.  *
  581.  *    For obvious reasons, this function is written in assembly language
  582.  *    and is very compiler specific.
  583.  */
  584.  
  585. #asm
  586.         .psect    bss,class=BSS
  587.         .align    2
  588. ;
  589. ;    Scratch pad values used by event glue code
  590. ;
  591.         .globl    __Lbss
  592. __old_ss:    .blkb    2
  593. __old_sp:    .blkb    2
  594. __old_ds:    .blkb    2
  595. __old_es:    .blkb    2
  596. #if    LARGE_DATA
  597.         .psect    lbss,local,class=LBSS,reloc=16,size=65535
  598. #endif
  599.         .blkb    GLUE_STACK_SIZE
  600. __glue_stack:
  601. ;
  602. #if    SMALL_CODE
  603.         .psect    _TEXT,class=CODE,reloc=16,size=65535
  604. #else
  605.         .psect    ltext,local,class=CODE,reloc=16,size=65535
  606. #endif
  607.         .align    16
  608. __asm_event_glue:
  609.         PUSHF                ;keep current flag state
  610.         CLI                ;ints off for the duration
  611.         CLD                ;direction forwards
  612.         PUSH    AX            ;keep event bits
  613.         PUSH    DS            ;and driver DS
  614.         MOV    AX,#seg(__Lbss)
  615.         MOV    DS,AX            ;setup user DS
  616.         POP    __old_ds
  617.         MOV    __old_es,ES
  618.         MOV    __old_ss,SS
  619.         MOV    __old_sp,SP        ;keep driver stack
  620.         MOV    ES,__old_ss        ;ES indexes old stack
  621.         MOV    AX,#seg(__glue_stack)
  622.         MOV    SS,AX
  623.         MOV    SP,#__glue_stack    ;setup our own stack
  624.         PUSH    CX
  625.         PUSH    BX
  626.         MOV    BX,__old_sp
  627.         MOV    AX,ES:[BX]        ;get driver AX value
  628. #if    SMALL_CODE
  629.         CALL    __c_event_glue_
  630. #else
  631.         CALLF    __c_event_glue_
  632. #endif
  633.         MOV    SS,__old_ss        ;get driver SS
  634.         MOV    SP,__old_sp        ;get driver SP
  635.         MOV    ES,__old_es        ;get driver ES
  636.         MOV    DS,__old_ds        ;get driver DS
  637.         POP    AX
  638.         POPF
  639.         RETF
  640. #endasm
  641.  
  642. /*
  643.  *    End of file: MOUSE.C
  644.  */
  645.